#include <iostream>
#include <vector>
#include <ctime>


#include "common.h"
#include "init.h" 



#define MAX_WALKS 5000
#define NODE_NUMBER 5
//groud is also considered as a node.
float testTopology[5][7]={
{0,1,0,1,0,25,VOLTAGECONSTANT},
{1,0,1,1,0,5,VOLTAGECONSTANT},
{0,1,0,1,1,0,VOLTAGECONSTANT},
{1,1,1,0,1,0,VOLTAGECONSTANT},
{0,0,1,1,0,0,0},      
};

//float testTopology[3][5]={
//{0,1,1,25,VOLTAGECONSTANT},
//{1,0,0.5,0,VOLTAGECONSTANT},
//{1,0.5,0,0,0},    
//};

int main ()
{ 
    
    
    UINT nodeSeq, walkTimes, nbrNums, relayNodeID, i,j,k, firstVisited, homeNodeFlag;
    float randomValue, lowBound, upBound;
    NODE NodesRecord[NODE_NUMBER];
    relayNode relayedNode;
  
    
    srand((unsigned int)time(NULL));
    topoInit ((float**)testTopology, NodesRecord, NODE_NUMBER);   //initilize the NodesRecord structure
    
    for (nodeSeq = 0; nodeSeq < NODE_NUMBER; nodeSeq++)          
    {
        //check whether this node's voltage has been known
        if (NodesRecord[nodeSeq].exactHomeFlag == 1 || NodesRecord[nodeSeq].unexactHomeFlag == 1)
        {
           continue;
        }
        
        //each node walks MAX_WALKS times
        for (walkTimes = 0; walkTimes < MAX_WALKS; walkTimes++)
        {
            relayNodeID = nodeSeq;
            while (1) // when the node come to a homenode, it stops this walk.
            {
                 randomValue = rand()%100+1;
                 nbrNums = NodesRecord[relayNodeID].neighborNodes.size();  //find out the neighbor nodes of a relay node.
                 
                 lowBound = 0;
                 homeNodeFlag = 0;
                 for (i = 0; i < nbrNums; i++)
                 {
                     upBound = NodesRecord[relayNodeID].neighborNodes[i].probability + lowBound;
                     if (lowBound < randomValue && randomValue <= upBound)
                     {
                      //record the information of the selected neighbor node
                          if (NodesRecord[relayNodeID].neighborNodes[i].homeFlag == 1)  //it is a homenode
                          {
                              homeNodeFlag = 1;
                          }
                       
                          //first check whether this relayNode has been visited by node nodeSeq
                          firstVisited = 1;
                           
                          for (j = 0; j < NodesRecord[nodeSeq].visitedNodes.size(); j++)
                          {
                              if (NodesRecord[nodeSeq].visitedNodes[j].nodeID == NodesRecord[relayNodeID].neighborNodes[i].nodeID)
                              {
                                   NodesRecord[nodeSeq].visitedNodes[j].visitedNum += 1;
                                   firstVisited = 0;                                       
                                   break;
                              }
                          }
                          
                          if (firstVisited)
                          {
                                relayedNode.nodeID = NodesRecord[relayNodeID].neighborNodes[i].nodeID;
                                relayedNode.visitedNum = 1;
                                relayedNode.homeFlag = NodesRecord[relayNodeID].neighborNodes[i].homeFlag; 
                                relayedNode.totalConductance = NodesRecord[relayNodeID].neighborNodes[i].totalConductance;
                                relayedNode.injectCurrent = NodesRecord[relayNodeID].neighborNodes[i].injectCurrent;
                                relayedNode.voltage = NodesRecord[relayNodeID].neighborNodes[i].voltage;
                                NodesRecord[nodeSeq].visitedNodes.push_back(relayedNode);
                          }
                          
                          relayNodeID = NodesRecord[relayNodeID].neighborNodes[i].nodeID;
                          //cout << relayNodeID << "" << endl;
                          break;            
                     }
                     
                     lowBound = upBound;
                 }
                 
                 //when the node come to a homenode, it stops this walk.
                 if (homeNodeFlag)
                 {
                      break;
                 }                    
            }
        }
        
        //compute the node's voltage
        NodesRecord[nodeSeq].voltage = 0;
        
        for (j = 0; j < NodesRecord[nodeSeq].visitedNodes.size(); j++)
        {
            //cout << NodesRecord[nodeSeq].visitedNodes[j].visitedNum << endl;
            if (NodesRecord[nodeSeq].visitedNodes[j].homeFlag)
            {
                NodesRecord[nodeSeq].voltage += NodesRecord[nodeSeq].visitedNodes[j].voltage * NodesRecord[nodeSeq].visitedNodes[j].visitedNum;
            }
            else
            {
                NodesRecord[nodeSeq].voltage += NodesRecord[nodeSeq].visitedNodes[j].visitedNum *(NodesRecord[nodeSeq].visitedNodes[j].injectCurrent/NodesRecord[nodeSeq].visitedNodes[j].totalConductance);
            }
            
             //cout << NodesRecord[nodeSeq].visitedNodes[j].totalConductance << endl;
            //cout << NodesRecord[nodeSeq].visitedNodes[j].injectCurrent/NodesRecord[nodeSeq].visitedNodes[j].totalConductance << endl;
            //cout << NodesRecord[nodeSeq].visitedNodes[j].visitedNum << endl;
            
        }
        NodesRecord[nodeSeq].voltage = NodesRecord[nodeSeq].voltage/MAX_WALKS + NodesRecord[nodeSeq].injectCurrent/NodesRecord[nodeSeq].totalConductance;
        cout <<  NodesRecord[nodeSeq].voltage << endl;
    }
  
    return 0;
}





